import openai
import os
import chardet
import charset_normalizer
from docx import Document
from pdfminer.high_level import extract_text
from typing import Optional

# API 配置
api_key = "sk-ThA0WI5NVgQ1xYUf8BriyRJfIqBWRvbV5rrzmAWBvdjxsnWP"
base_url = "https://yibuapi.com/v1"


def detect_encoding(file_path: str) -> Optional[str]:
    """
    智能检测文件编码，尝试多种方法提高准确率
    """
    try:
        # 读取前100KB用于编码检测
        with open(file_path, 'rb') as f:
            raw_data = f.read(102400)

        # 优先使用charset_normalizer（更准确）
        cn_result = charset_normalizer.detect(raw_data)
        if cn_result['confidence'] > 0.9:
            return cn_result['encoding']

        # 备选：使用chardet
        chardet_result = chardet.detect(raw_data)
        if chardet_result['confidence'] > 0.8:
            return chardet_result['encoding']

        # 尝试常见编码
        common_encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1', 'utf-16']
        for encoding in common_encodings:
            try:
                with open(file_path, 'r', encoding=encoding) as f:
                    f.read(1024)  # 尝试读取一小段
                return encoding
            except:
                continue

        print("警告：无法确定文件编码，默认使用utf-8")
        return 'utf-8'

    except Exception as e:
        print(f"编码检测错误: {e}")
        return 'utf-8'


def read_file_content(file_path: str) -> str:
    """
    读取文件内容，支持多种文件类型
    """
    try:
        # 根据文件扩展名选择读取方式
        if file_path.lower().endswith('.docx'):
            return read_docx(file_path)
        elif file_path.lower().endswith('.pdf'):
            return read_pdf(file_path)
        elif file_path.lower().endswith(('.txt', '.csv', '.md', '.json', '.xml', '.html')):
            return read_text_file(file_path)
        else:
            return f"错误：不支持的文件类型: {os.path.splitext(file_path)[1]}"

    except Exception as e:
        return f"文件读取失败: {str(e)}"


def read_text_file(file_path: str) -> str:
    """读取文本文件（使用自动检测的编码）"""
    encoding = detect_encoding(file_path)
    print(f"检测到文件编码: {encoding}")

    with open(file_path, 'r', encoding=encoding) as f:
        return f.read()


def read_docx(file_path: str) -> str:
    """读取Word文档"""
    doc = Document(file_path)
    return '\n'.join(para.text for para in doc.paragraphs)


def read_pdf(file_path: str) -> str:
    """读取PDF文件"""
    return extract_text(file_path)


def get_openai_response(file_content: str, question: str, api_key: str, base_url: str) -> str:
    """
    基于文件内容和问题向OpenAI发送请求
    """
    try:
        # 限制上下文长度，避免超出模型最大token限制
        max_context_length = 12000  # 根据模型调整
        if len(file_content) > max_context_length:
            print(f"警告：文件内容过长，截断至{max_context_length}字符")
            file_content = file_content[:max_context_length]

        full_prompt = f"根据以下文本内容回答问题：\n\n{file_content}\n\n问题：{question}"

        client = openai.OpenAI(api_key=api_key, base_url=base_url)
        response = client.chat.completions.create(
            model="gpt-4-turbo",
            messages=[{"role": "user", "content": full_prompt}]
        )

        return response.choices[0].message.content

    except Exception as e:
        return f"请求失败: {str(e)}"


if __name__ == "__main__":
    # 配置文件路径
    desktop_path = r"D:\桌面\竞赛\挑战杯+人工智能"
    file_name = "第3章 数据获取.docx"
    file_path = os.path.join(desktop_path, file_name)

    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"错误：文件不存在 - {file_path}")
    else:
        print(f"正在处理文件: {file_name}")

        # 读取文件内容
        file_content = read_file_content(file_path)

        if "文件读取失败" in file_content or "错误" in file_content:
            print(file_content)
        else:
            print(f"成功读取文件，内容长度: {len(file_content)} 字符")

            # 自定义问题
            user_question = "假如你是一个智能考试机器人，请你根据知识库总结出一道主观性题目来考察我"

            # 发送请求
            print("\n正在向AI提问...")
            response = get_openai_response(file_content, user_question, api_key, base_url)

            # 输出结果
            print(f"\n问题: {user_question}")
            print("回答:")
            print("-" * 50)
            print(response)
            print("-" * 50)